Skip to content

feat: SimulatorImaging(use_jax=True) + xp-aware preprocess noise - #335

Merged
Jammy2211 merged 1 commit into
mainfrom
feature/simulator-imaging-use-jax
May 24, 2026
Merged

feat: SimulatorImaging(use_jax=True) + xp-aware preprocess noise#335
Jammy2211 merged 1 commit into
mainfrom
feature/simulator-imaging-use-jax

Conversation

@Jammy2211

Copy link
Copy Markdown
Collaborator

Summary

PR 2 of Phase 2 (z_features/jax_user_intro.md). Adds use_jax=True to aa.SimulatorImaging and routes the Poisson noise pipeline through jax.random on the JAX path.

Eager JAX path works (simulator.via_image_from with use_jax=True returns Imaging with jax.Array data — useful for batched simulations and parameter sweeps). @jax.jit wrapping is currently blocked by an unrelated Array2D.native jit-incompatibility in autoarray's slim/native reshape machinery — flagged in the simulator docstring; needs a separate PR.

Companion changes in PyAutoLens (autolens/imaging/simulator.py) and PyAutoGalaxy (autogalaxy/imaging/simulator.py) — those PRs forward xp from the new _xp property on the parent.

API Changes

  • Added: aa.SimulatorImaging(..., use_jax=False) constructor flag.
  • Added: aa.SimulatorImaging._xp property (returns jnp if use_jax, else np).
  • Changed signature: aa.SimulatorImaging.via_image_from(xp=None) — defaults to self._xp when None.
  • Changed signature: preprocess.poisson_noise_via_data_eps_from(..., xp=np) and preprocess.data_eps_with_poisson_noise_added(..., xp=np) gain xp parameter; JAX path uses jax.random.PRNGKey(noise_seed) + jax.random.poisson.
  • Changed behaviour: the if xp.isnan(noise_map.array).any(): NaN-guard now only fires on the NumPy path (Python if on a JAX tracer triggers TracerBoolConversionError).

See full details below.

Test Plan

  • 3 new unit tests in test_autoarray/dataset/imaging/test_simulator_use_jax.py — constructor wiring, _xp property, via_image_from(xp=None) auto-fallback. Numpy-only assertions per [[feedback_no_jax_in_unit_tests]].
  • All 831 PyAutoArray tests pass (no regressions to existing test_simulator.py).
  • Cross-xp parity script at autolens_workspace_test/scripts/imaging/simulator_use_jax_parity.py confirms eager NumPy and JAX paths produce identical simulated images to atol=1e-8 for a noise-free Sersic + Isothermal lens. (Ships with the workspace_test follow-up.)
Full API Changes (for automation & release notes)

Added

  • aa.SimulatorImaging(use_jax: bool = False) constructor parameter.
  • aa.SimulatorImaging._xp property — returns jax.numpy if self.use_jax, else numpy.

Changed signature

  • aa.SimulatorImaging.via_image_from(image, over_sample_size=None, xp=None)xp now defaults to None, meaning "fall back to self._xp". Explicit xp=np or xp=jnp still honoured.
  • preprocess.poisson_noise_via_data_eps_from(data_eps, exposure_time_map, seed=-1, xp=np) — new xp parameter.
  • preprocess.data_eps_with_poisson_noise_added(data_eps, exposure_time_map, seed=-1, xp=np) — new xp parameter.

Changed behaviour

  • aa.SimulatorImaging.via_image_from: the NaN-noise-map runtime guard now only runs on the NumPy path. Under JAX it would trigger TracerBoolConversionError because Python if <tracer>: is not allowed. JAX users must confirm exposure_time / background_sky_level are large enough themselves.
  • preprocess.poisson_noise_via_data_eps_from on the JAX path: uses jax.random.PRNGKey(seed) + jax.random.poisson instead of np.random.poisson. seed=-1 (random per call) derives a time-based PRNGKey.

Migration

  • No breaking changes. Existing call sites with xp=np or no xp= continue to work unchanged — use_jax defaults to False.
  • New canonical pattern for JAX-eager simulation:
    import autoarray as aa
    simulator = aa.SimulatorImaging(exposure_time=300.0, psf=psf, use_jax=True)
    dataset = simulator.via_image_from(image=my_image)  # Imaging with jax.Array data

Known limitations

  • @jax.jit wrap of via_image_from is currently blocked by a pre-existing autoarray limitation: Array2D.native routes through array_2d_via_indexes_from (indexed assignment of native-index tuples) which is not jit-traceable. Needs a separate slim/native reshape refactor PR.

Out of scope (separate PRs)

  • aa.SimulatorInterferometer.use_jax=True + signature symmetry fix (Phase 2 PR 3).
  • xp=np + jnp-backed-grid mismatch ValueError in AbstractMaker.__init__ (Phase 2 PR 4).
  • Array2D.native jit-safety refactor (separate task).

🤖 Generated with Claude Code

Adds use_jax constructor flag to aa.SimulatorImaging and threads xp through
via_image_from. When use_jax=True, via_image_from defaults xp=jnp via a new
_xp property; the simulator's Poisson noise generation routes through
jax.random.PRNGKey(noise_seed) instead of numpy's RNG.

Also adds xp=np parameter to preprocess.poisson_noise_via_data_eps_from and
preprocess.data_eps_with_poisson_noise_added so the JAX path routes through
jax.random.poisson.

The Python `if xp.isnan(noise_map.array).any():` runtime guard is now NumPy-
side only — under JAX it would trigger TracerBoolConversionError. JAX users
must confirm their exposure_time / background_sky_level are large enough
themselves; JAX silently propagates NaN through the trace.

Eager JAX path works: simulator.via_image_from with use_jax=True returns an
Imaging with jax.Array data. @jax.jit wrapping is currently blocked by an
unrelated PyAutoArray limitation: Array2D.native is not jit-traceable
because array_2d_via_indexes_from uses indexed assignment of native-index
tuples. A separate PyAutoArray task is needed to refactor the slim/native
reshape path. The simulator docstring flags this.

Part of Phase 2 PR 2 of z_features/jax_user_intro.md. Companion changes:
PyAutoLens + PyAutoGalaxy simulator subclass overrides thread xp through
via_tracer_from / via_galaxies_from.

Design doc: admin_jammy/notes/jax_interface.md
Issue: PyAutoArray#334

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@Jammy2211 Jammy2211 added the pending-release PR queued for the next release build label May 24, 2026
@Jammy2211
Jammy2211 merged commit 0787ff3 into main May 24, 2026
6 checks passed
@Jammy2211
Jammy2211 deleted the feature/simulator-imaging-use-jax branch May 24, 2026 15:40
@Jammy2211 Jammy2211 removed the pending-release PR queued for the next release build label Sep 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant